#!/usr/local/bin/perl -w
#////////////////////////////////////////////////////////////
#
# lisa.pl	
#  * list user aliases and forwards
#  * list group membership information
#
#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
#
# author: Marcin Wisnios <wisnios@gmail.com>
#
# This script is a part of Commandline Support Tools project
# http://code.google.com/p/cs-tools/
#
#////////////////////////////////////////////////////////////

use strict;
use warnings;

use Carp qw(carp croak);
use Term::ReadKey;
use Net::LDAP;
use Switch;

my $LDHOST = 'ldap.localdomain';
my $LDPORT = '389';
my $BASE   = 'o=isp';
my $DN;
my $PWFILE;
my $PW;
my $DOMAIN;
my $USER;
my $GROUP;

my $query;
my @aliases;
my @forwards;
my @imembers;
my @emembers;
my @values;
my $row;


while (my $arg = shift @ARGV) {
	switch ($arg) {
	  case('-lh') { $LDHOST = shift @ARGV; }
	  case('-lp') { $LDPORT = shift @ARGV; }
	  case('-ld') { $DN = shift @ARGV; }
	  case('-lb') { $BASE = shift @ARGV; }
	  case('-lf') { $PWFILE = shift @ARGV; }
	  case('-dn') { $DOMAIN = shift @ARGV; }
	  case('-u') { $USER = shift @ARGV; }
	  case('-g') { $GROUP = shift @ARGV; }
	  case('-h') {
		print "usage: $0 [options]\n";
		print "options:\n";

		print "\t-lh host\tLDAP server name or IP address";
		$LDHOST && print " (default: $LDHOST)";
		print "\n";

		print "\t-lp port\tLDAP server TCP port number";
		$LDPORT && print " (default: $LDPORT)";
		print "\n";

		print "\t-lb basedn\tbase dn";
		$BASE && print " (default: $BASE)";
		print "\n";

		print "\t-ld binddn\tbind dn";
		$DN && print " (default: $DN)";
		print "\n";

		print "\t-lf file\tread bind passwd";
		$PWFILE && print " (default: $PWFILE)";
		print "\n";

		print "\t-dn domain\tdomain name";
		$DOMAIN && print " (default: $DOMAIN)";
		print "\n";

		print "\t-u mail\t\tlist user aliases\n";
		print "\t-g mail\t\tlist group members\n";
		print "\t-h\t\tdisplay usage information\n";
		exit;
	  }
	}
}


my $ldap = Net::LDAP->new($LDHOST, port => $LDPORT) or croak $@;

my $ldapline ="ldap: $LDHOST:$LDPORT\n";
print $ldapline;

for (2..length($ldapline)) {
        print '%';
}
print "\n";

if ($DN) {
	print "bind dn: $DN\n";
}
else {
	print "bind dn: ";
	$DN = <>;
	chomp($DN);
}

if ($PWFILE) {
	open(my $PWF, '<', $PWFILE) or croak("$PWFILE: $!");

	$PW = <$PWF>;
	chomp($PW);
	print "bind pw: (hidden)\n";

	close($PWF);
}
else {
	print "bind passwd: ";
	ReadMode('noecho');
	$PW= <>;
	ReadMode('restore');
	chomp($PW);

	print "\n";
}

my $mesg = $ldap->bind($DN, password => $PW) or croak $@;
if ($mesg->code) {
	print $mesg->error,"\n";
	exit;
}

if ($BASE) {
	print "base dn: $BASE\n";
}
else {
	print "base dn: ";
	$BASE = <>;
	chomp($BASE);
}

if ($DOMAIN) {
	print "domain: $DOMAIN\n";
}
else {
	print "domain: ";
	$DOMAIN = <>;
	chomp($DOMAIN);
}

if ($USER) {
	$query = $ldap->search(base => "o=$DOMAIN,$BASE", filter => "(mail=$USER)");
}
else {
	$query = $ldap->search(base => "o=$DOMAIN,$BASE", filter => "(uid=*)");
}
foreach ($query->entries) {
	print "\nmail: " . $_->get_value('mail') . "\n";

	@aliases = $_->get_value('mailAlternateAddress', asref => 1);
	if (@aliases) {
		foreach $row (@aliases) {
			@values = split(/ /, "@$row");
			foreach (@values) {
				print "+ " . $_ . "\n";
			}
		}
	}
	else {
		print "+ no aliases\n";
	}

	@forwards = $_->get_value('mailForwardingAddress', asref => 1);
	if (@forwards) {
		foreach $row (@forwards) {
			@values = split(/ /, "@$row");
			foreach (@values) {
				print "> " . $_ . "\n";
			}
		}
	}
	else {
		print "> no forwards\n";
	}
}

if ($GROUP) {
	$query = $ldap->search(base => "o=$DOMAIN,$BASE", filter => "(mail=$GROUP)");
}
else {
	$query = $ldap->search(base => "o=$DOMAIN,$BASE", filter => "(inetMailGroupStatus=active)");
}
foreach ($query->entries) {
	print "\ngroup: " . $_->get_value('mail') . "\n";

	@imembers = $_->get_value('uniqueMember', asref => 1);
	if (@imembers) {
		foreach $row (@imembers) {
			@values = split(/ /, "@$row");
			foreach (@values) {
				$_ =~ s/uid=(.*?),.*=(.*?),$BASE/$1\@$2/;
				print "] " . $_ . "\n";
			}
		}
	}
	else {
		print "] no internal members\n";
	}

	@emembers = $_->get_value('mgrpRFC822MailMember', asref => 1);
	if (@emembers) {
		foreach $row (@emembers) {
			@values = split(/ /, "@$row");
			foreach (@values) {
				print "[ " . $_ . "\n";
			}
		}
	}
	else {
		print "[ no external members\n";
	}
}

$ldap->unbind;
